#include "PacketListener.h"
#include <errno.h>
#include <iphlpapi.h>
#include <mstcpip.h>
#include <stdio.h>
#include <winsock2.h>

PacketListener::PacketListener (const char* ip, SafeQueue<Packet_t>& queue):packetQueue(queue) {
    this->ip = ip;
    listener = setupRawSocket();
    // this->loop->runInLoop([&] {
	// 	printf("-- PacketListener Listening on %s in tid %ld --\n", this->ip ,hv_gettid());
	// 	//Logger::LOG("info", "Packet Listner", "Running in tid " + hv_gettid());
	// 	while (true) {
	// 		int len = recv(listener, (char*)buffer, sizeof(buffer), 0);
	// 		if (len == SOCKET_ERROR) { //err
	// 			Logger::ERR("recv() failed: "+ WSAGetLastError(),"search err code");
	// 		}
	// 		else {
	// 			auto packet = copy(buffer, len);
	// 			produce(packet);
	// 		}
	// 	}
	// });
}

void PacketListener::startListening() {
    this->listeningThread.start();
}

void PacketListener::stopListening() {
    this->listeningThread.stop();
}

PacketListener::~PacketListener() {
    if (this->loop->isRunning()) {
        this->loop->stop();
    }
    closesocket(listener);
    WSACleanup();
}


//Windows下
SOCKET PacketListener::setupRawSocket() {
	//https://github.com/nospaceships/raw-socket-sniffer
    WSAData wsaData;
    int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        Logger::ERR("WSAStartup failed:"+iResult, "seach for the err code");
    }

    SOCKET sd = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
    if (sd == INVALID_SOCKET) {
        Logger::ERR("socket() failed: %u" + WSAGetLastError(),"seach for the err code");
    }

	// Captured IP packets sent and received by the network interface the
	// specified IP address is associated with.
	struct sockaddr_in addr;
	addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr(ip);
    addr.sin_port = htons(0);
    // Bind the socket to the specified IP address.
    int rc = bind(sd, (struct sockaddr*)&addr, sizeof(addr));
    if (rc == SOCKET_ERROR) {
        Logger::ERR("bind() failed: failed: % u" + WSAGetLastError(), "seach for the err code");
    }
    
    // Give us ALL IPv4 packets sent and received to the specific IP address.
    int value = RCVALL_IPLEVEL;
    DWORD out = 0;
    rc = WSAIoctl(sd, SIO_RCVALL, &value, sizeof(value), NULL, 0, &out, NULL, NULL);
    if (rc == SOCKET_ERROR) {
        Logger::ERR("WSAIoctl() failed: " + WSAGetLastError(), "seach for the err code");
    }
    return sd;
}